import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter

# 修改纵轴刻度格式
plt.gca().yaxis.set_major_formatter(ScalarFormatter(useMathText=False))
plt.gca().yaxis.get_major_formatter().set_scientific(False)  # 禁用科学计数法
plt.gca().yaxis.get_major_formatter().set_useOffset(False)  # 禁用偏移量


# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 设置随机种子，确保结果可复现
np.random.seed(42)

# 参数设定
initial_state = 0  # 初始天气状态，0代表好天气
states = ['好天气', '坏天气']
profit_good_weather_base = 10000  # 好天气下的基础利润
profit_bad_weather_base = 8000  # 坏天气下的基础利润


# 模拟市场波动（波动因子），模拟市场价格变化对利润的影响
def market_volatility():
    return np.random.normal(1, 0.2)  # 市场波动因子，均值为1，标准差为0.2


# 随机噪声引入，模拟更多随机因素
def random_noise():
    return np.random.normal(0, 10)


# 随机土地健康状态（0代表健康，1代表贫瘠）
def random_land_status():
    return np.random.choice([0, 1], p=[0.7, 0.3])  # 健康土地的概率为0.7，贫瘠土地的概率为0.3


# 动态生成转移矩阵
def dynamic_transition_matrix(weather_state, market_factor, land_status):
    """
    根据当前天气状态、市场波动因子和土地状态动态生成转移矩阵。
    """
    # 基本的转移概率
    base_transition_matrix = np.array([[0.8, 0.2],  # 好天气 -> 好天气的概率0.8，坏天气的概率0.2
                                       [0.4, 0.6]])  # 坏天气 -> 好天气的概率0.4，坏天气的概率0.6

    # 市场波动对转移矩阵的影响，市场波动因子可能使得天气的转移概率发生变化
    market_factor_adjustment = np.random.normal(0, 0.1) * market_factor

    # 土地状态对转移矩阵的影响，贫瘠土地可能使坏天气的概率增加
    land_status_adjustment = 0.1 if land_status == 1 else 0  # 贫瘠土地使得坏天气的概率增加

    # 动态调整转移矩阵
    if weather_state == 0:  # 当前是好天气
        transition_matrix = np.array([[0.8 + market_factor_adjustment, 0.2 - market_factor_adjustment],
                                      [0.4 + land_status_adjustment, 0.6 - land_status_adjustment]])
    else:  # 当前是坏天气
        transition_matrix = np.array([[0.8 - market_factor_adjustment, 0.2 + market_factor_adjustment],
                                      [0.4 - land_status_adjustment, 0.6 + land_status_adjustment]])

    # 确保概率和为1
    transition_matrix = np.clip(transition_matrix, 0, 1)  # 防止出现负概率或大于1的概率
    transition_matrix[0] = transition_matrix[0] / transition_matrix[0].sum()  # 标准化
    transition_matrix[1] = transition_matrix[1] / transition_matrix[1].sum()  # 标准化

    return transition_matrix


# 计算利润（加入了衰退因素）
def calculate_profit(state, market_factor, land_status, iteration, total_iterations):
    # 利润的衰退：随着迭代次数增加，利润逐渐趋于平稳
    decay_factor = max(1 - iteration / total_iterations, 0.2)  # 衰退因子，防止过于剧烈的衰退

    if state == 0:  # 好天气
        noise = random_noise()
        profit = profit_good_weather_base * (0.9 + 0.3 * np.sin(np.random.uniform(0, 2 * np.pi))) * market_factor
        profit *= decay_factor  # 衰退影响
        profit += noise
    else:  # 坏天气
        noise = random_noise()
        profit = profit_bad_weather_base * (0.8 + 0.1 * np.random.randn()) * market_factor
        profit *= decay_factor  # 衰退影响
        profit += noise

    return max(profit, 0)  # 保证利润不能为负


# 模拟马尔可夫链的迭代过程
def simulate_markov_chain(steps, initial_state=0):
    state = initial_state
    profits = []
    for iteration in range(steps):
        market_factor = market_volatility()  # 获取市场波动因子
        land_status = random_land_status()  # 获取土地健康状态
        profit = calculate_profit(state, market_factor, land_status, iteration, steps)  # 计算当前状态下的利润
        profits.append(profit)

        # 动态生成转移矩阵
        transition_matrix = dynamic_transition_matrix(state, market_factor, land_status)

        # 进行状态转移
        state = np.random.choice([0, 1], p=transition_matrix[state])

    return profits


# 不考虑不确定性因素的情况下的利润（简单假设每次固定利润，未加入市场波动）
def simulate_without_uncertainty(steps):
    return [profit_good_weather_base] * steps


# 模拟的迭代次数
iterations = 14000

# 计算利润
profits_with_uncertainty = simulate_markov_chain(iterations)
profits_without_uncertainty = simulate_without_uncertainty(iterations)

# 计算累计利润
cumulative_profit_with_uncertainty = np.cumsum(profits_with_uncertainty)
cumulative_profit_without_uncertainty = [44951538] * iterations  # 固定值 40,000,000

plt.figure(figsize=(10, 6))

# 修改纵轴刻度格式，避免科学计数法
plt.gca().yaxis.set_major_formatter(ScalarFormatter(useMathText=False))
plt.gca().yaxis.get_major_formatter().set_scientific(False)  # 禁用科学计数法
plt.gca().yaxis.get_major_formatter().set_useOffset(False)  # 禁用偏移量

# 绘制累计利润曲线
plt.plot(cumulative_profit_with_uncertainty, label='Profit taking into account uncertainties', color='b', linestyle='-',
         linewidth=2)
plt.plot(cumulative_profit_without_uncertainty, label='Profit without taking into account random factors', color='r', linestyle='--', linewidth=2)

# 图表设置
plt.title("Profit comparison taking into account random factors", fontsize=16)
plt.xlabel("The number of iterations", fontsize=14)
plt.ylabel("Profit (RMB)", fontsize=14)
plt.legend()
plt.grid(True)

# 保存图表为图片
plt.savefig('111_fixed.png')  # 保存为当前路径下的PNG文件

# 显示图表
plt.show()
